const CARD = {
    COLOR: {
        RED: 'RED',
        GREEN: 'GREEN',
        PURPLE: 'PURPLE'
    },
    QUANTITY: {
        ONE: 'ONE',
        TWO: 'TWO',
        THREE: 'THREE'
    },
    SHAPE: {
        RIPPLE: 'RIPPLE', //波纹
        DIAMOND: 'DIAMOND', //方块
        OVAL: 'OVAL' //椭圆
    },
    FILL: {
        STRIPE: 'STRIPE', //条纹
        HOLLOW: 'HOLLOW', //空心
        SOLID: 'SOLID', //实心
    }
}

const _getColor = card => {
    let index = parseInt(card)
    if (index % 9 >= 1 && index % 9 <= 3) {
        return CARD.COLOR.RED
    } else if (index % 9 >= 4 && index % 9 <= 6) {
        return CARD.COLOR.PURPLE
    } else {
        return CARD.COLOR.GREEN
    }
}

const _getQuantity = card => {
    let index = parseInt(card)
    if (index % 3 === 1) {
        return CARD.QUANTITY.ONE
    } else if (index % 3 === 2) {
        return CARD.QUANTITY.TWO
    } else {
        return CARD.QUANTITY.THREE
    }
}

const _getShape = card => {
    let index = parseInt(card)
    if (index % 27 >= 1 && index % 27 <= 9) {
        return CARD.SHAPE.RIPPLE
    } else if (index % 27 >= 10 && index % 27 <= 18) {
        return CARD.SHAPE.DIAMOND
    } else {
        return CARD.SHAPE.OVAL
    }
}


const _getFill = card => {
    let index = parseInt(card)

    if (index >= 1 && index <= 27) {
        return CARD.FILL.SOLID
    } else if (index >= 28 && index <= 54) {
        return CARD.FILL.STRIPE
    } else {
        return CARD.FILL.HOLLOW
    }
}

const _checkProperties = properties => {
    if (properties.length !== 3) {
        return false
    }

    if (
        (properties[0] === properties[1] && properties[1] === properties[2] && properties[2] === properties[0])
        || (properties[0] !== properties[1] && properties[1] !== properties[2] && properties[2] !== properties[0])) {
        return true
    }
    return false
}

const _combinations = (a, c) => {
    let index = []
    let n = a.length

    for (let j = 0; j < c; j++)
        index[j] = j
    index[c] = n

    let ok = true
    let result = []

    while (ok) {

        let comb = []
        for (let j = 0; j < c; j++)
            comb[j] = a[index[j]]
        result.push(comb)

        ok = false

        for (let j = c; j > 0; j--) {
            if (index[j - 1] < index[j] - 1) {
                index[j - 1]++
                for (let k = j; k < c; k++)
                    index[k] = index[k - 1] + 1
                ok = true
                break
            }
        }
    }

    return result
}


const check = cards => {
    if (cards.length !== 3) {
        return false
    }

    let matrix = [];

    for (let i = 0; i < 3; i++) {
        matrix[i] = []
        matrix[i].push(_getColor(cards[i]))
        matrix[i].push(_getQuantity(cards[i]))
        matrix[i].push(_getShape(cards[i]))
        matrix[i].push(_getFill(cards[i]))
    }

    let bingo = true;

    for (let i = 0; i < 4; i++) {
        bingo = _checkProperties([matrix[0][i], matrix[1][i], matrix[2][i]])
        if (!bingo) {
            break;
        }
    }

    return bingo
}


const find = allCards => {
    let combinations = _combinations(allCards, 3);

    let result = [];

    combinations.forEach(cards => {
        if (check(cards)) {
            result.push(cards)
        }
    })
    return result
}


export {
    check,
    find
}